/**
 * 
 */
package imoney.client.gwt;

import java.util.ArrayList;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;

import static imoney.client.gwt.GwtUtils.redirect;
import imoney.client.handler.BlurPrefilText;
import imoney.client.handler.CommaKeyHandler;
import imoney.client.handler.FocusEmptyText;
import imoney.client.rpc.GroupService;
import imoney.client.rpc.GroupServiceAsync;

import imoney.shared.CookieBuilderShared;
import imoney.shared.Statics;
import imoney.shared.exception.AlreadyExistingException;
import imoney.shared.exception.NoSuchPersonException;
import imoney.shared.exception.PositionOutOfDateException;
import imoney.shared.model.Group;
import static imoney.shared.UrlUtils.createRedirURL;

/**
 * A class to create the user interface for group management.
 * @author Arnaud PELOQUIN
 *
 */
public class GroupsUI implements EntryPoint {

	/**
	 * Playground of the module.
	 */
	private VerticalPanel mainpanel = new VerticalPanel();
	/**
	 * The table where to display the current groups of the user.
	 */
	FlexTable groupTable = new FlexTable();

	/**
	 * The table holding the group creation components.
	 */
	FlexTable groupCreationTable = new FlexTable();

	Label pseudoLabel = new Label();

	/**
	 * RPC service to manage user groups.
	 */
	GroupServiceAsync gpService = GWT.create(GroupService.class);

	@Override
	public void onModuleLoad() {
		String cookValue = Cookies.getCookie(Statics.Cookie_INDEX_OF_PERSON);
		if (cookValue == null) {
			// no cookie, the user has to be logged to the application.
			redirect(createRedirURL(Statics.LOGGIN_URL, Window.Location.getHref(), ""));
		} else {
			buildUI(cookValue);
			getCurrentGroups(cookValue);
		}
	}

	private void buildUI(String cookValue) {
		RootPanel.get("groups").add(mainpanel);
		pseudoLabel.setText(CookieBuilderShared.readPseudo(cookValue));
		mainpanel.add(pseudoLabel);
		mainpanel.add(groupTable);
		mainpanel.add(groupCreationTable);
		buildGroupCreation();
	}

	private void buildGroupCreation() {
		// new Group Name
		TextBox textName = new TextBox();
		String textPrefil = "Group Name";
		textName.setText(textPrefil);
		textName.addFocusHandler(new FocusEmptyText(textName, textPrefil));
		textName.addBlurHandler(new BlurPrefilText(textName, textPrefil));
		groupCreationTable.setWidget(0, 1, textName);
		// new Group first Pseudo box
		TextBox textPseudos = new TextBox();
		String textPrefil2 = "People Names";
		textPseudos.setText(textPrefil2);
		textPseudos.addFocusHandler(new FocusEmptyText(textPseudos, textPrefil2));
		textPseudos.addBlurHandler(new BlurPrefilText(textPseudos, textPrefil2));
		textPseudos.addKeyPressHandler(new CommaKeyHandler(textPseudos, textPrefil2, groupCreationTable, 0));
		groupCreationTable.setWidget(0, 2, textPseudos);
		// save button. placed to the left because it is simpler for now.
		Button button = new Button("Save");
		button.addClickHandler(new GroupSaveHandler());
		groupCreationTable.setWidget(0, 0, button);
	}


	/**
	 * Gets the current groups of the logged user via RPC, and displays them in a table.
	 */
	public void getCurrentGroups(String cookieValue) {
		// AsyncCallback object creation.
		gpService.getGroups(cookieValue, new AsyncCallback<ArrayList<Group>>() {
			@Override
			public void onFailure(Throwable caught) {
				if (caught instanceof PositionOutOfDateException) {
					// have to do it again because inside the callback
					String cookieValue = Cookies.getCookie(Statics.Cookie_INDEX_OF_PERSON);
					int position = ((PositionOutOfDateException) caught).getRealPosition();
					Cookies.setCookie(Statics.Cookie_INDEX_OF_PERSON, CookieBuilderShared.updatePosition(cookieValue, position));
					// TODO recall to get information ?
				} else if (caught instanceof NoSuchPersonException) {
					redirect(createRedirURL(Statics.LOGGIN_URL, Window.Location.getHref(), ""));						
				} else {
					caught.printStackTrace();
					redirect(Statics.DEFAULT_ERROR_URL);
				}
			}
			@Override
			public void onSuccess(ArrayList<Group> result) {
				groupTable.setText(groupTable.getRowCount(), 0, "Your current groups :");
				for(Group group : result) {
					displayGroup(group);
				}
			}
		});
	}

	private void displayGroup(Group gp) {
		int row = groupTable.getRowCount();
		groupTable.setText(row, 1, gp.getName());
		String names = "";
		for(String persName : gp.getMembres()) {
			names += persName+", ";
		}
		names = names.substring(0, names.length()-2);
		groupTable.setText(row, 2, names);
	}

	private class GroupSaveHandler implements ClickHandler {
		@Override
		public void onClick(ClickEvent event) {
			// group name
			TextBox textb = (TextBox) groupCreationTable.getWidget(0, 1);
			String gpname = textb.getText();
			gpname = gpname.replaceAll(",", ""); // coma chars deletion
			gpname = gpname.replaceAll(" ","");	 // space chars deletion
			// people names
			int nbcols = groupCreationTable.getCellCount(0);
			ArrayList<String> people = new ArrayList<String>();
			people.add(CookieBuilderShared.readPseudo(Cookies.getCookie(Statics.Cookie_INDEX_OF_PERSON)));
			for(int col=2; col<nbcols; col++) {
				TextBox tb = (TextBox) groupCreationTable.getWidget(0, col);
				String name = tb.getText();
				name = name.replaceAll(",", ""); // coma chars deletion
				name = name.replaceAll(" ","");	 // space chars deletion
				people.add(name);
			}
			gpService.saveGroup(gpname, people, new AsyncCallback<Group>(){
				@Override
				public void onFailure(Throwable caught) {
					if (caught instanceof AlreadyExistingException) {
						int rowIdx = groupTable.getRowCount();
						groupTable.setText(rowIdx, 0, "Group name already in use: ");
						groupTable.setText(rowIdx, 1, "Group name already in use: ");
					} else if (caught instanceof NoSuchPersonException) {
						int rowIdx = groupTable.getRowCount();
						groupTable.setText(rowIdx, 0, "Pseudos not found: ");
						int col = 1;
						for (String pseud : ((NoSuchPersonException) caught).getPseudos()) {
							groupTable.setText(rowIdx, col, pseud);
							col++;
						}

					} else {
						caught.printStackTrace();					
					}
				}
				@Override
				public void onSuccess(Group group) {
					displayGroup(group);
				}
			});
		}
	}

}
